package com.bbzn.device.client.controller;

import com.alibaba.fastjson.JSONObject;
import com.bbzn.device.client.vo.req.GroupDeviceVO;
import com.bbzn.device.client.vo.req.ManyVideoCallVO;
import com.bbzn.device.client.vo.req.MassVO;
import com.bbzn.device.client.aspect.OperationAnnotation;
import com.bbzn.device.client.config.EmqCode;
import com.bbzn.device.client.config.EmqxMqttProperties;
import com.bbzn.device.client.config.Oauth2Constant;
import com.bbzn.device.client.constant.*;
import com.bbzn.device.client.dao.mqttsub.EmqApiPublishEntity;
import com.bbzn.device.client.dataobject.MessHis;
import com.bbzn.device.client.dataobject.NbOrderStrategy;
import com.bbzn.device.client.dataobject.OrderStrategy;
import com.bbzn.device.client.dataobject.SystemParam;
import com.bbzn.device.client.dto.ct.data.ProductUnionDTO;
import com.bbzn.device.client.exception.DefinitException;
import com.bbzn.device.client.service.*;
import com.bbzn.device.client.service.emq.order.OrderSendStrategy;
import com.bbzn.device.client.service.emq.order.NbOrderSendStrategy;
import com.bbzn.device.client.service.emq.order.impl.nb.NbMassMessagingImpl;
import com.bbzn.device.client.service.impl.cwting.UnifySendServiceImpl;
import com.bbzn.device.client.utils.*;
import com.ctg.ag.sdk.biz.aep_device_command.CreateCommandResponse;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author wulongbo
 * @Date 2021/12/14 10:18
 * @Version 1.0
 */

@RestController
@RequestMapping("/order")
@Slf4j
@Api(value = "", tags = "指令下发 ")
public class OrderSendController extends BaseApiService {

    @Autowired
    private GroupDeviceService groupDeviceService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private OrderStrategyService orderStrategyService;

    @Autowired
    private NbOrderStrategyService nbOrderStrategyService;

    @Autowired
    private NbMassMessagingImpl nbMassMessagingImpl;

    @Autowired
    private SystemParamByCacheService systemParamByCacheService;

    @Autowired
    public UnifySendServiceImpl unifySendService;

    @Resource
    private EmqxMqttProperties emqxMqttProperties;

    @Autowired
    private EmqApiService emqApiService;

    @Autowired
    private PublishService publishService;

    @Autowired
    private SimpleMongoService simpleMongoService;

    /**
     * 指令下发
     *
     * @param map
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/orderSend", method = RequestMethod.POST)
    @OperationAnnotation(content = "指令下发")
    public BaseResponse orderSend(@RequestBody Map map, HttpServletRequest request) throws Exception {
        String secretKey = commonService.getWebSalt(request);
        String userName = MayiktJwtUtils.getUsername(request, secretKey);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Object codeType = map.get("code");
        Object imei = map.get("imei");
        if (codeType == null) {
            SystemParam systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_TYPE_ID_PREFIX + language);
            throw new DefinitException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, systemParam.getMassage());
        }
        map.put("code", codeType.toString());
        /*if (!EnumUtil.isInclude(NbOrderEnum.class, (Integer) codeType)) {
            SystemParam systemParam = systemParamByCacheService.getValues(ProductConstant.PRODUCT_ENUM, ProductConstant.PRO_NO_ACCESS_TYPE_PREFIX + language);
            throw new DefinitException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, systemParam.getMassage());
        }*/
        if (!OptionalBean.ofNullable(imei).isPresent()) {
            SystemParam systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        ProductUnionDTO productUnionDTO = groupDeviceService.getDeviceDetailByImei(imei.toString());
        if (productUnionDTO == null) {
            SystemParam systemParam = systemParamByCacheService.getValues(CustomerConstant.CUSTOMER_ENUM, CustomerConstant.IMEI_UN_EXIST_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        // NB卡
        if (OptionalBean.ofNullable(productUnionDTO.getNbDeviceId()).isPresent()) {
            productUnionDTO.setUserName(userName);
            NbOrderStrategy orderStrategy = nbOrderStrategyService.findByChannelCode(Integer.parseInt(codeType.toString()));
            String strategyBeanId = orderStrategy.getStrategyBeanId();
            // 使用beanid从容器获取对象
            NbOrderSendStrategy nbOrderStrategy = SpringUtils.getBean(strategyBeanId, NbOrderSendStrategy.class);
            CreateCommandResponse createCommandResponse = nbOrderStrategy.sendOrder(map, productUnionDTO, language);
            System.out.println(createCommandResponse.toString());
        } else {
            // 根据code查询具体业务实现
            OrderStrategy orderStrategy = orderStrategyService.findByChannelCode(Integer.parseInt(codeType.toString()));
            String strategyBeanId = orderStrategy.getStrategyBeanId();
            // 使用beanid从容器获取对象
            OrderSendStrategy orderSendStrategy = SpringUtils.getBean(strategyBeanId, OrderSendStrategy.class);
            orderSendStrategy.sendMessage(map, language);
        }
        SystemParam systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.ORDER_SEND_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }


    /**
     * 组内消息群发
     *
     * @param groupDeviceVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/massMessaging", method = RequestMethod.POST)
    @OperationAnnotation(content = "组内消息群发")
    public BaseResponse massMessaging(@RequestBody GroupDeviceVO groupDeviceVO, HttpServletRequest request) throws Exception {
        String secretKey = commonService.getWebSalt(request);
        String userName = MayiktJwtUtils.getUsername(request, secretKey);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        if (!OptionalBean.ofNullable(groupDeviceVO.getGroupId()).isPresent()) {
            SystemParam systemParam = systemParamByCacheService.getValues(GroupConstant.GROUP_ENUM, GroupConstant.GROUP_NO_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        String content = groupDeviceVO.getContent();
        if (StringUtils.isEmpty(content)) {
            SystemParam systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_CONTENT_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        // 1. 查询组内设备
        List<ProductUnionDTO> productUnionDTOS = groupDeviceService.getInGroupDeviceExceptSelf(null, groupDeviceVO.getGroupId());
        if (CollectionUtils.isEmpty(productUnionDTOS)) {
            SystemParam systemParam = systemParamByCacheService.getValues(GroupConstant.GROUP_ENUM, GroupConstant.GROUP_NO_DEVICE_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        // 2. 筛选NB设备
        List<ProductUnionDTO> nb = productUnionDTOS.stream().filter(p -> p.getNBProductId() != null).collect(Collectors.toList());
        // 3. 筛选出非NB设备
        List<String> union = productUnionDTOS.stream().filter(p -> p.getNBProductId() == null).map(ProductUnionDTO::getImei)
                .collect(Collectors.toList());
        // NB卡
        Map map = new HashMap();
        map.put("code", EmqCode.massMessaging);
        map.put("content", Base64Util.decode(content));
        List<MessHis> messHisList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(nb)) {
            nb.parallelStream().forEach(opt -> {
                        opt.setUserName(userName);
                        map.put("imei", opt.getImei());
                        try {
                            nbMassMessagingImpl.sendOrder(map, opt, language);
                            MessHis messHis = saveMessHis(opt.getImei(), groupDeviceVO.getGroupId().toString(), userId, content, userName);
                            messHisList.add(messHis);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
            );
        }
        union.stream().parallel().forEach(imei -> {
            MessHis messHis = saveMessHis(imei, groupDeviceVO.getGroupId().toString(), userId, content, userName);
            messHisList.add(messHis);
        });

        // 非NB卡
        // 记录消息群发操作
        String topic = groupDeviceService.getTopic(groupDeviceVO.getGroupId());
        // 推送立即重启topic给设备
        JSONObject data = new JSONObject();
        data.put("code", EmqCode.massMessaging);
        // 主键id-->只有这条是接收topic需要用到的
        data.put("content", content);
        publishService.sendToMqtt(data.toJSONString(), topic);
        if (CollectionUtils.isNotEmpty(messHisList)) {
            simpleMongoService.insertMulti(messHisList, MongoDbConstant.MESS_HIS);

        }
        SystemParam systemParam = systemParamByCacheService.getValues(CrudConstant.CRUD_ENUM, CrudConstant.ADD_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    private MessHis saveMessHis(String imei, String groupId, Long userId, String message, String userName) {
        MessHis messHis = new MessHis();
        messHis.setImei(imei);
        messHis.setMessId(groupId);
        messHis.setUserId(userId);
        messHis.setMessage(message);
        messHis.setCreatedBy(userName);
        messHis.setCreateTime(System.currentTimeMillis());
        messHis.setUpdatedBy(userName);
        messHis.setUpdateTime(System.currentTimeMillis());
        return messHis;
    }

    /**
     * 随机组合消息群发
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/massMessagingTemp", method = RequestMethod.POST)
    @OperationAnnotation(content = "随机组合消息群发")
    public BaseResponse massMessagingTemp(@RequestBody MassVO reqVO, HttpServletRequest request) throws Exception {
        String secretKey = commonService.getWebSalt(request);
        String userName = MayiktJwtUtils.getUsername(request, secretKey);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        Long userId = commonService.getUserId(request);
        List<String> imeis = reqVO.getImeis();
        if (CollectionUtils.isEmpty(imeis)) {
            SystemParam systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        String content = reqVO.getContent();
        if (StringUtils.isEmpty(content)) {
            SystemParam systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_CONTENT_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        // 筛选出NB设备
        List<ProductUnionDTO> nb = groupDeviceService.getProductUnionDTOList(imeis);
        List<MessHis> messHisList = new ArrayList<>();
        String messId = imeis.stream().map(imei -> imei.substring(0, 3)).collect(Collectors.joining(""));
        //筛选非出NB设备
        List<EmqApiPublishEntity> mq = imeis.stream().filter(
                imei -> !nb.stream().collect(Collectors.toSet()).contains(imei)).map(m -> {
            EmqApiPublishEntity entity = new EmqApiPublishEntity();
            entity.setQos(2);
            entity.setClientid(Oauth2Constant.CLIENT_PRE + m);
            entity.setTopics(EmqCode.sendTopic + m + EmqCode.endTopic);
            JSONObject payload = new JSONObject();
            payload.put("code", EmqCode.massMessaging);
            // 主键id-->只有这条是接收topic需要用到的
            payload.put("imei", m);
            payload.put("content", content);
            entity.setPayload(payload.toJSONString());
            MessHis messHis = saveMessHis(m, messId, userId, content, userName);
            messHisList.add(messHis);
            return entity;
        }).collect(Collectors.toList());
        // NB卡
        Map map = new HashMap();
        map.put("code", "3015");
        map.put("content", Base64Util.decode(content));
        if (CollectionUtils.isNotEmpty(nb)) {
            nb.parallelStream().forEach(opt -> {
                        opt.setUserName(userName);
                        map.put("imei", opt.getImei());
                        try {
                            nbMassMessagingImpl.sendOrder(map, opt, language);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
            );
        }

        // 非NB卡
        // EMQ 指定客户端主题批量订阅 topic
        String url = emqxMqttProperties.getHostUrl();
        String postUri = Oauth2Constant.EMQ_API_HTTP
                + url.substring(0, url.lastIndexOf(":")).substring(url.indexOf(":")) + Oauth2Constant.EMQ_API_PUBLISHBATCH_ADR;
        emqApiService.publishBatch(postUri, mq);
        if (CollectionUtils.isNotEmpty(messHisList)) {
            simpleMongoService.insertMulti(messHisList, MongoDbConstant.MESS_HIS);

        }
        SystemParam systemParam = systemParamByCacheService.getValues(CrudConstant.CRUD_ENUM, CrudConstant.ADD_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

    /**
     * 随机组合多人菊风视频或语音通话
     * NB 没有此功能
     *
     * @param reqVO
     * @param request
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/manyVideoCallToJuphoon", method = RequestMethod.POST)
    @OperationAnnotation(content = "随机组合多人菊风视频或语音通话")
    public BaseResponse manyVideoCallToJuphoonTemp(@RequestBody ManyVideoCallVO reqVO, HttpServletRequest request) throws Exception {
        String secretKey = commonService.getWebSalt(request);
        String userName = MayiktJwtUtils.getUsername(request, secretKey);
        String language = MayiktJwtUtils.getLanguage(request, secretKey);
        List<String> imeis = reqVO.getImeis();
        if (CollectionUtils.isEmpty(imeis)) {
            SystemParam systemParam = systemParamByCacheService.getValues(DeviceConstant.DEVICE_ENUM, DeviceConstant.DEVICE_NO_IMEI_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.getRoomId()).isPresent()) {
            SystemParam systemParam = systemParamByCacheService.getValues(VideoCallConstant.VIDEO_CALL_ENUM, VideoCallConstant.VIDEO_CALL_UN_ROOM_ID_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.isHide()).isPresent()) {
            SystemParam systemParam = systemParamByCacheService.getValues(VideoCallConstant.VIDEO_CALL_ENUM, VideoCallConstant.VIDEO_CALL_UN_IS_HIDE_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }
        if (!OptionalBean.ofNullable(reqVO.isVideo()).isPresent()) {
            SystemParam systemParam = systemParamByCacheService.getValues(VideoCallConstant.VIDEO_CALL_ENUM, VideoCallConstant.VIDEO_CALL_UN_IS_VIDEO_PREFIX + language);
            throw new DefinitException(systemParam.getCode(), systemParam.getMassage());
        }

        // 筛选出NB设备
        List<ProductUnionDTO> nb = groupDeviceService.getProductUnionDTOList(imeis);

        //筛选非出NB设备
        List<EmqApiPublishEntity> mq = imeis.stream().filter(
                imei -> !nb.stream().collect(Collectors.toSet()).contains(imei)).map(m -> {
            EmqApiPublishEntity entity = new EmqApiPublishEntity();
            entity.setQos(2);
            entity.setClientid(Oauth2Constant.CLIENT_PRE + m);
            entity.setTopics(EmqCode.sendTopic + m + EmqCode.endTopic);
            JSONObject payload = new JSONObject();
            payload.put("code", EmqCode.VoiceCode);
            // 主键id-->只有这条是接收topic需要用到的
            payload.put("imei", m);
            payload.put("roomId", reqVO.getRoomId());
            payload.put("isHide", reqVO.isHide());
            payload.put("video", reqVO.isVideo());
            entity.setPayload(payload.toJSONString());
            return entity;
        }).collect(Collectors.toList());

        // 非NB卡
        // EMQ 指定客户端主题批量订阅 topic
        String url = emqxMqttProperties.getHostUrl();
        String postUri = Oauth2Constant.EMQ_API_HTTP
                + url.substring(0, url.lastIndexOf(":")).substring(url.indexOf(":")) + Oauth2Constant.EMQ_API_PUBLISHBATCH_ADR;
        emqApiService.publishBatch(postUri, mq);
        SystemParam systemParam = systemParamByCacheService.getValues(CrudConstant.CRUD_ENUM, CrudConstant.ADD_SUCCESS_PREFIX + language);
        return setResultSuccess(systemParam.getMassage());
    }

}
